下面列出這次用到的openapi,
可以看到他有一個共通的domain https://cloud.culture.tw/frontsite
然後後面分成 trans 跟 opendata,後續又根據功能不同拆成多個類別
節慶相關
https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindFestivalTypeJ
主題推薦
https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindIssueTypeJ
藝文活動-所有類別
https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=all
音樂表演資訊
https://cloud.culture.tw/frontsite/trans/SearchShowAction.do?method=doFindTypeJ&category=1
查詢單一活動詳細資料
https://cloud.culture.tw/frontsite/opendata/activityOpenDataJsonAction.do?method=doFindActivityById&id=5a64e3d8c6355e2a94b8a1cf
經緯度查詢附近未過期活動
https://cloud.culture.tw/frontsite/opendata/activityOpenDataJsonAction.do?method=doFindActivitiesNearBy&lat=25.051345&lon=121.549569&range=2
查詢單一類別未過期活動資料
https://cloud.culture.tw/frontsite/opendata/activityOpenDataJsonAction.do?method=doFindActivitiesByCategory&category=1
首先在src下建立一個 api資料夾,建立 api.js 檔。
import axios from 'axios';
// 建立一個axios實例
const publicService = axios.create({
baseURL: 'https://cloud.culture.tw/frontsite', // url = base url + request url
});
時間有限所以先做節慶活動跟主題推薦這2隻api,
會更新主題推薦主頁、節慶活動主頁、節慶活動詳細頁面 3個頁面!
// 節慶活動 api
// eslint-disable-next-line import/prefer-default-export
export const getFestival = data => publicService.get('/trans/SearchShowAction.do?method=doFindFestivalTypeJ', data);
// 主題推薦 api
export const getTopic = data => publicService.get('/trans/SearchShowAction.do?method=doFindIssueTypeJ', data);
這頁比較簡單一點,在TopicPage裡,我把資料逐筆塞進Topic 子組件,沒有做其他操作
所以只要修改TopicPage的資料來源,Topic子組件就會自動吃到新的資料
<script>
import Topic from './Topic';
import { getTopic } from '../api/api'; // 從api.js import 主題推薦的api方法
export default {
name: 'TopicPage',
components: { Topic },
data() {
return {
title: '', // 原本這邊都是寫死的假資料,直接改成空值即可
note: '',
issue: [],
};
},
methods: {
getTopicData() { // 寫一個接資料的方法
getTopic() // 呼叫api方法
.then((res) => {
this.title = res.data.title; // 把api回傳的值存到data的參數裡
this.note = res.data.note;
this.issue = res.data.issue;
})
.catch((err) => {
// eslint-disable-next-line no-console
console.log(err);
});
},
},
created() {
this.getTopicData(); // 生命週期函數,在頁面初始化時要執行資料
},
};
</script>
成功! 如果有看過 Day21 的應該會發現Title跟下面的活動內容都更新了!
而且後續api資料更新,這頁的資料也會自動刷新~
這頁跟主題推薦差不多,都是迴圈渲染組件,所以就不贅述啦
<script>
import Festival from './Festival';
import { getFestival } from '../api/api';
export default {
name: 'FestivalPage',
components: { Festival },
data: () => ({
date: null,
form: {
keyword: null,
start: null,
end: null,
location: [],
},
locations: ['臺北市', '基隆市', '新北市', '宜蘭縣', '桃園市', '新竹市', '新竹縣', '苗栗縣', '臺中市', '彰化縣', '南投縣', '雲林縣', '嘉義縣', '嘉義市', '臺南市', '高雄市', '屏東縣', '澎湖縣', '花蓮縣', '台東縣', '金門縣', '連江縣'],
festivalList: [],
}),
methods: {
getFestivalData() {
getFestival()
.then((res) => {
this.festivalList = res.data;
})
.catch((err) => {
// eslint-disable-next-line no-console
console.log(err);
});
},
},
created() {
this.getFestivalData();
},
};
</script>
這頁就略為複雜了,他一樣是要用節慶專區的api,
但是拿到的是全部資料,還需要再從中篩選出頁面對應的那筆
跟上面2個一樣,把假資料改為空值,在create()的地方引入api方法
有更改的地方我會用註解標註
<script>
import { getFestival } from '../api/api'; //引入api方法
export default {
name: 'FestivalDetailPage',
data: () => ({
actId: 0,
actData: {},
festivalList: [], // 把原本的假資料改為空值
}),
methods: {
//獲取全部資料
getAllData() {
getFestival()
.then((res) => {
this.festivalList = res.data; //先把全部資料存入data()
this.getActData(); // 挑出這頁要用的那筆資料
})
.catch((err) => {
// eslint-disable-next-line no-console
console.log(err);
});
},
getActData() {
const actId = this.$route.query.actId;
let selectedAct;
this.festivalList.forEach((obj) => {
if (obj.actId === parseInt(actId, 10)) {
selectedAct = obj;
}
});
this.actData = selectedAct;
},
getImageUrl(imageUrl) {
return `https://cloud.culture.tw/${imageUrl}`;
},
getDateFormat(datetime) {
const newDate = new Date(Date.parse(datetime));
return `${newDate.getFullYear()}/${newDate.getMonth() + 1}/${newDate.getDate()}`;
},
getGrade() {
const { grade1, grade2, grade3, grade4, grade5, grade6 } = this.actData;
const gradeList = [grade1, grade2, grade3, grade4, grade5, grade6];
let gradeResult = '';
gradeList.forEach((grade) => {
if (grade) {
gradeResult += (`${grade} `);
}
});
return gradeResult;
},
},
created() {
this.getAllData(); //在頁面初始化時戳api拿資料
},
};
</script>
更改完後,頁面可以正常顯示了,但是好像有點小問題
錯誤訊息如下,可以看到本來應該帶imageUrl的地方,它卻拿到undefined,所以報錯
雖然圖片顯示正常,但是有error我們還是要處理一下!
這個問題是因為我原本的資料是放在data()裡,
然後template裡用 getImageUrl() 去把圖片欄位換成正確的網址,轉換後才會渲染頁面
<v-img :src='getImageUrl(actData.imageUrl)' />
getImageUrl(imageUrl) {
return `https://cloud.culture.tw/${imageUrl}`;
},
那現在變成頁面初始化時,因為data的值我們改成空值了,getImageUrl時會拿不到資料 報錯,
然後才執行create() 裡的方法,去把api撈到的資料存到data裡
用文字講比較難理解,直接上圖!
原本的寫法在左邊,因為直接拿data的資料所以會正常顯示不報錯
改拿api資料後,他會先拿一次資料,執行完create()後又拿一次,所以頁面會正常顯示但是第一次失敗後會報錯誤訊息
既然第二次拿的到資料,就代表第一次的拿資料是不必要的
只要保留讓api撈取後可以把資料存進data,再讓他渲染這段即可
<!-- 改成直接拿data裡的資料 -->
<v-img :src='actData.imageUrl'/>
// 移除getImageUrl(),直接在取得單筆資料時,更改image格式
getActData() {
const actId = this.$route.query.actId;
let selectedAct;
this.festivalList.forEach((obj) => {
if (obj.actId === parseInt(actId, 10)) {
selectedAct = obj;
}
});
this.actData = selectedAct;
this.actData.imageUrl = `https://cloud.culture.tw/${this.actData.imageUrl}`;
},
好惹~ api的部分就先講到這邊啦
後續其實還有挺多東西要做的,不過時間有限真的是講不完
29天了,明天來講一下目前的成果總結
快完賽啦 oh ya